/*
TRABALHO DE PROGRAMACAO CONCORRENTE 2013
FEITO POR:
Danilo Augusto Silva, 6418678
Felipe Fukakusa, 6426976
Jader Bruno Pereira Lima, 6792346
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/time.h>


#define MAX_TAMANHO_PALAVRA 10000
#define MAX_TAMANHO_SENTENCA 1000000
#define TRUE 1
#define FALSE 0

//VERIFICA SE O NUMERO N EH PRIMO. EM CASO POSITIVO, INCREMENTA A VARIAVEL TOTALPRIMOS (PASSADA POR REFERENCIA)
int verificaPrimo(int *n, int *totalPrimos){
	//VARIAVEIS
	int i, j;	
	int aux_raiz;
	int aux_boolean = TRUE;
	 
	int vetorCrivo[*n];

	aux_raiz = sqrt( *n );

	//PREENCHIMENTO DO VETOR DE PRIMOS
	for(i = 2; i <= *n; i++) {
		vetorCrivo[i] = i;
	}

	
	for(i = 2; i <= aux_raiz; i++) {
	
		//VETOR EH ZERADO NAS POSICOES NAO PRIMOS
		for( j = 2*i ; j <= *n ; j=j+i )
			vetorCrivo[j] = 0; 

	}

	//ALGORITMO DE CHECAGEM SE N EH PRIMO
	for(i = 2; i <= aux_raiz && aux_boolean; i++){
		if ( vetorCrivo[i] ){
			if((*n % vetorCrivo[i]) == 0){
				aux_boolean = FALSE;
			}	
		}
	}
	
	if (aux_boolean){
		*totalPrimos += 1;
	}
	
	
}

//RETIRA OS CARACTERES QUE NAO SAO LETRAS E NUMEROS DA VARIAVEL TEXTO PASSADA POR REFERENCIA
void limpaTexto(char *texto){
	
	//VARIAVEIS
	//INICIALIZACAO DO VETOR DE CARACTERES INVALIDOS (A SER RETIRADOS DOS TEXTOS)
	char invalidos[] = ". , ; : / ? ! [ ] { } ( ) < > # $ % ^ * ' | ~ + - _ @";
	invalidos[ strlen( invalidos ) ] = '"';

	char aux_texto[ strlen( texto ) ];
	int i, j, k = 0;
	int aux_boolean = FALSE;

	for(i = 0; i < strlen(texto); i++) {
		//PARA CADA CHAR, VERIFICA SE NAO ESTA PRESENTE NO VETOR DE CHARS INVALIDOS
		for(j = 0; j < strlen( invalidos ) && !aux_boolean; j++) {
			if(texto[i] == invalidos[j])
				aux_boolean = TRUE;
			if(texto[i] == '\t')
				aux_boolean = TRUE;
		}

		if(!aux_boolean)
			aux_texto[k++] = texto[i];
		else
			aux_boolean = FALSE;
	}	
	aux_texto[k] = '\0';
	//COPIA O O TEXTO LIMPO PARA A VARIAVEL TEXTO INICIAL
	strcpy(texto, aux_texto);
}

//VERIFICA, PARA CADA PALAVRA DA SENTENCA PASSADA POR PARAMETRO, SE E UM PALINDROMO. EM CASO POSITIVO VERIFICA SE A SOMA DOS CODIGOS ASCCI DE SUAS LETRAS EH NUMERO PRIMO.
void verificaPalindromoNaPalavra(char *texto, int *totalPalavras, int *totalPalindromos, int *totalPrimos ){
	//VARIAVEIS	
	int n, k;
	int totalAscii = 0;
	int aux_boolean;
	int i = 0 ,j = 0, l;
	char palavra[MAX_TAMANHO_PALAVRA];
	
	//printf("TEXTO: %s\n", texto);
	//printf("STRLEN: %d\n", strlen(texto));
	
	//REPETIR PARA TODAS AS LETRAS DA SENTENCA
	while( i < ( strlen( texto )) + 1 ) {
		//RECUPERA AS PALAVRAS DA SENTENCA (SEPARADAS POR VIRGULA OU ESPACO OU PONTO)
		if( texto[i] != ',' && texto[i] != '\0' && texto[i] != ' ' && texto[i] != '\n') {
			//COLOCA TODAS AS LETRAS EM MINUSCULA
			if( isupper( texto[i] ) )
				texto[i] = tolower( texto[i] );

			palavra[j++] = texto[i];
			palavra[j] = '\0';
		} else {
			j = 0;

			limpaTexto(palavra);
			//printf("PALAVRA: %s\n", palavra);

			//DEFINIMOS QUE UM PALINDROMO DEVE TER 2 LETRAS OU MAIS
			if( strlen( palavra ) > 2 ) {
				//printf("PALAVRA > 2: %s\n", palavra);				
				//printf("STRLEN: %d\n", strlen(palavra));				
				aux_boolean = TRUE;
				l = 0;
				n = strlen( palavra );
				k = n/2;

				//TOTAL DO MAPEAMENTO INICIA COM O MAPEAMENTO DA LETRA QUE ESTA NO MEIO
				if(n%2 == 1)				
					totalAscii = palavra[k];
				else
					totalAscii = 0;
				//MAPEAMENTO DO CODIGO ASCII PARA CADA LETRA
				while( aux_boolean && l < k ) {
					if( palavra[l] == palavra[n - l - 1] ) 
						totalAscii += ( 2 * palavra[l++] );
					else
						aux_boolean = FALSE;	
				}
				
				if(aux_boolean) {
					//printf("PALINDROMO: %s\n", palavra);
					//printf("%s - %d\n", palavra, totalAscii);					
					*totalPalindromos += 1;
					verificaPrimo( &totalAscii, totalPrimos );
				} 
			}
		}
		i++;
		*totalPalavras += 1;
	}
}

int main(){
	//VARIAVEIS	
	int totalPalindromos = 0, totalPrimos = 0, totalPalavras = 0, i = 0;;
	int palindromoPal = 0, palindromoSen = 0, primoPal = 0, primoSen = 0;
	char texto[MAX_TAMANHO_SENTENCA], c;
	FILE *file;
	struct timeval startTime;
	struct timeval endTime;

	if( !( file = fopen( "wikipedia.txt", "r" ) ) ) {
		printf( "ERRO: ao abrir o arquivo\n" );
		exit( EXIT_FAILURE );
	}
		
	printf("EXECUTANDO PROGRAMA PALINDROMO SEQUENCIAL (TEXTO MAIOR)...\n");	

	//INICIA O CRONOMETRO		
	gettimeofday( &startTime, NULL );
	double inicio = startTime.tv_sec + ( startTime.tv_usec / 1000000.0 );
 
	//LE TODAS AS SENTENCAS DO TEXTO DE ENTRADA E PARA CADA UMA VERIFICA SE SUAS PALAVRAS SAO PALINDROMOS
	while( !feof( file ) ) {

		fscanf(file, "%c", &c);

		while(c != '\n'){
			
			texto[i++] = c;
			fscanf(file, "%c", &c);
		}
		texto[i] = '\0';
		i = 0;
		
		//printf("%s\n\n", texto);

		verificaPalindromoNaPalavra( 	texto, 
						&totalPalavras, 
						&totalPalindromos, 
						&totalPrimos );
	}
	
	gettimeofday( &endTime, NULL );
	double fim = endTime.tv_sec + ( endTime.tv_usec / 1000000.0 );

	printf( "Total Palavras: %d - Total Palavras Palindromos: %d - Total Palavras Primos: %d\n",  
						totalPalavras,
						totalPalindromos, 
						totalPrimos 	);	

	
	printf( "Tempo de execução total: %.3lf segundos\n", fim - inicio );


	
	fclose( file );

	exit( EXIT_SUCCESS );

}



